package executor

import (
	"context"
	"encoding/json"
	"errors"
	"smart-flow/server/config"
	"smart-flow/server/logger"
	"smart-flow/server/net"
	"smart-flow/server/redis"
	"smart-flow/server/utils"

	"go.uber.org/zap"

	redisLib "github.com/go-redis/redis/v8"
)

func InitExecutor() {
	loadExecutor(config.IspCustom)
	loadExecutor(config.IspTelecom)
	loadExecutor(config.IspMobile)
	loadExecutor(config.IspUnicom)
	loadNotV6Executor(config.IspCustom)
	loadNotV6Executor(config.IspTelecom)
	loadNotV6Executor(config.IspMobile)
	loadNotV6Executor(config.IspUnicom)
}

func loadExecutor(isp string) {
	var nextCursor uint64 = 0
	var keys []string
	var err error
	anyKey := utils.GenIspAnyKey(config.FlowManageKey, isp)
	for {
		keys, nextCursor, err = redis.RDB.HScan(context.Background(), anyKey, nextCursor, "*", 1000).Result()
		if err != nil {
			if errors.Is(err, redisLib.Nil) {
				return
			}
			logger.Logger.Error("[任务] Executor操作Redis异常", zap.Error(err))
			return
		}
		var agentCtx net.AgentContext
		for i := 0; i < len(keys); i += 2 {
			_ = json.Unmarshal([]byte(keys[i+1]), &agentCtx)
			ExecutingInstance(isp).AddExecutor(agentCtx.Uid, &agentCtx)
		}
		if nextCursor == 0 {
			break
		}
	}
	logger.Logger.Info("[任务] Executor加载完成", zap.String("isp:", config.GetIspHuman(isp)))
}

func loadNotV6Executor(isp string) {
	var nextCursor uint64 = 0
	var keys []string
	var err error
	anyKey := utils.GenIspAnyKey(config.FlowNotV6Key, isp)
	for {
		keys, nextCursor, err = redis.RDB.HScan(context.Background(), anyKey, nextCursor, "*", 1000).Result()
		if err != nil {
			if errors.Is(err, redisLib.Nil) {
				return
			}
			logger.Logger.Error("[任务] NotV6Executor操作Redis异常", zap.Error(err))
			return
		}
		var agentCtx net.AgentContext
		for i := 0; i < len(keys); i += 2 {
			_ = json.Unmarshal([]byte(keys[i+1]), &agentCtx)
			ExecutingInstance(isp).AddNotV6Executor(agentCtx.Uid, &agentCtx)
		}
		if nextCursor == 0 {
			break
		}
	}
	logger.Logger.Info("[任务] NotV6Executor加载完成", zap.String("isp:", config.GetIspHuman(isp)))
}
